#include "StdAfx.h"
#include "SimpleFileWrapper.h"


CSimpleFileWrapper::CSimpleFileWrapper(void)
	: _handle(INVALID_HANDLE_VALUE)
	, _name(_T(""))
{
}


CSimpleFileWrapper::~CSimpleFileWrapper(void)
{
	close();
}

BOOL CSimpleFileWrapper::open( const std::string& file_name, const UINT open_flags )
{
	if (INVALID_HANDLE_VALUE != _handle)
		return FALSE;

	_name = file_name;
	DWORD file_access = NULL;
	DWORD file_share = NULL;

	switch (open_flags & 3)
	{
	case of_mode_read:
		file_access = GENERIC_READ;
		break;
	case of_mode_write:
		file_access = GENERIC_WRITE;
		break;
	case of_mode_read_write:
		file_access = GENERIC_READ | GENERIC_WRITE;
		break;
	default: return FALSE;
	}

	switch (open_flags & 0x70)    // map compatibility mode to exclusive
	{
	case of_share_exclusive:
		file_share = 0;
		break;
	case of_share_deny_read:
		file_share = FILE_SHARE_WRITE;
		break;
	case of_share_deny_write:
		file_share = FILE_SHARE_READ;
		break;
	case of_share_deny_none:
		file_share = FILE_SHARE_WRITE | FILE_SHARE_READ;
		break;
	default:
		return FALSE;
	}

	DWORD create_flags = NULL;
	if (open_flags & of_mode_create)
	{
		if (open_flags & of_mode_no_truncate)
			create_flags = OPEN_ALWAYS;
		else
			create_flags = CREATE_ALWAYS;
	}
	else
		create_flags = OPEN_EXISTING;

	SECURITY_ATTRIBUTES sa;
	sa.nLength = sizeof(sa);
	sa.lpSecurityDescriptor = NULL;
	sa.bInheritHandle = (open_flags & of_mode_no_inherit) == 0;

	DWORD os_flags = FILE_ATTRIBUTE_NORMAL;
	if (open_flags & of_os_no_buffer)
		os_flags |= FILE_FLAG_NO_BUFFERING;
	if (open_flags & of_os_write_through)
		os_flags |= FILE_FLAG_WRITE_THROUGH;
	if (open_flags & of_os_random_access)
		os_flags |= FILE_FLAG_RANDOM_ACCESS;
	if (open_flags & of_os_sequential_scan)
		os_flags |= FILE_FLAG_SEQUENTIAL_SCAN;

	_handle = ::CreateFile(_name.c_str(), file_access, file_share, &sa, create_flags, os_flags, NULL);

	ATLTRACE(_T("CreateFile result: %d\n"), GetLastError());

	return (INVALID_HANDLE_VALUE != _handle);
}

UINT CSimpleFileWrapper::read( VOID* buf, const UINT& count )
{
	if ((nullptr == buf) || 
		(NULL == count) || 
		(UINT(-1) == count) ||
		(INVALID_HANDLE_VALUE == _handle))
			return NULL;

	DWORD read_count;
	if (FALSE == ::ReadFile(_handle, buf, count, &read_count, NULL))
		return FALSE;

	return (UINT)read_count;
}

UINT CSimpleFileWrapper::write(const VOID* buf, const UINT& count )
{
	if ((nullptr == buf) || 
		(NULL == count) || 
		(UINT(-1) == count) ||
		(INVALID_HANDLE_VALUE == _handle))
			return NULL;

	DWORD write_count;
	if (FALSE == ::WriteFile(_handle, buf, count, &write_count, NULL))
	{
		ATLTRACE(_T("WriteFile error: %d\n"), GetLastError());
		return NULL;
	}

	return write_count;
}

ULONGLONG CSimpleFileWrapper::seek( const LONGLONG& pos_off, const UINT& pos_from )
{
	if (INVALID_HANDLE_VALUE == _handle)

	if ((sp_begin != pos_from) || (sp_current != pos_from) || (sp_end != pos_from))
		return NULL;

	LARGE_INTEGER off;
	off.QuadPart = pos_off;
	off.LowPart = ::SetFilePointer(_handle, off.LowPart,
										&off.HighPart,
										(DWORD)pos_from);
	if (off.LowPart  == (DWORD)-1)
	{
		if (NO_ERROR != ::GetLastError())
		{
			return NULL;
		}
	}

	return off.QuadPart;
}

ULONGLONG CSimpleFileWrapper::get_position() const
{
	if (INVALID_HANDLE_VALUE == _handle)
		return NULL;

	LARGE_INTEGER pos;
	pos.QuadPart = 0;
	pos.LowPart = ::SetFilePointer(_handle, pos.LowPart, &pos.HighPart , FILE_CURRENT);
	if (pos.LowPart == (DWORD)-1)
		if (NO_ERROR != ::GetLastError())
			return NULL;

	return pos.QuadPart;
}

BOOL CSimpleFileWrapper::flush()
{
	if (INVALID_HANDLE_VALUE == _handle)
		return FALSE;

	return ::FlushFileBuffers(_handle);
}

BOOL CSimpleFileWrapper::close()
{
	if (INVALID_HANDLE_VALUE == _handle)
		return FALSE;

	_name.clear();
	BOOL result = ::CloseHandle(_handle);
	_handle = INVALID_HANDLE_VALUE;

	return result;
}

BOOL CSimpleFileWrapper::set_lenght( const ULONGLONG& new_lenght )
{
	if (INVALID_HANDLE_VALUE == _handle)
		return FALSE;

	seek(new_lenght, (UINT)sp_begin);

	return ::SetEndOfFile(_handle);
}

ULONGLONG CSimpleFileWrapper::get_lenght() const
{
	if (INVALID_HANDLE_VALUE == _handle)
		return NULL;

	ULARGE_INTEGER file_size;
	file_size.LowPart = ::GetFileSize(_handle, &file_size.HighPart);
	if (file_size.LowPart == INVALID_FILE_SIZE)
		if (::GetLastError() != NO_ERROR)
			return NULL;

	return file_size.QuadPart;
}

HANDLE CSimpleFileWrapper::get_handle() const
{
	return _handle;
}



